/*
   Zii EGGxplorer - A simple Zii file browser

   Copyright (C) 2009 - 2010 Claudio Corti

   Implementation file for EGGxplorer class, derived from CSkinApp; required for application to run.
*/

// C++ standard library
#include <cstdlib>

// Plaszma library
#include <skin.h>

// Application headers
#include "EGGxplorer.h"
#include "resources.h"

// Singleton access to the application
EGGxplorer *EGGxplorer::GetApplication()
{
   if (!CPlaszmaApp::mpAppSingleInstance) CPlaszmaApp::mpAppSingleInstance = new EGGxplorer();
   return (EGGxplorer*) CPlaszmaApp::mpAppSingleInstance;
}

// Destructor
EGGxplorer::~EGGxplorer()
{
}

// Application constructor
EGGxplorer::EGGxplorer() : main_window(NULL), res_factory(NULL), string_res(NULL), image_res(NULL),
                           layout_studio(NULL), skin_factory(NULL), desktop_observer(NULL)
{
}

// Called when the application call Run (redefinition of virtual function)
bool EGGxplorer::OnRun()
{
   // Initialize base class
   CSkinApp::OnRun();

   // Setup the resource studio
   res_factory = new CResourceStudio;
   if (res_factory == NULL) return false;

   // Create the string resource from the string resource file
   string_res = res_factory->Create("EGGxplorer.plr");
   if (string_res == NULL) return false;
   // Set language based on the locale set in the OS
   char lang[LOCALE_SIZE];
   Desktop_GetLanguage(lang, LOCALE_SIZE);
   string_res->Set(STRINGRESOURCE_PROPERTY_LOCALE, lang, strlen(lang));

   // Create the image resource factory
   image_res = res_factory->Create("EGGxplorer.pir");
   if (image_res == NULL) return false;

   // Set up the Layout Studio from the configuration file
   layout_studio = new CLayoutStudio("EGGxplorer.cfg");
   if (layout_studio == NULL) return false;

   // Add the string and image resource to the layout studio
   layout_studio->AddResourceHandle(string_res);
   layout_studio->AddResourceHandle(image_res);

   // Create the standard Skin widget factory for the layout studio
   skin_factory = CLayoutSkinFactory::Create(layout_studio);
   if (skin_factory == NULL) return false;

   // Create the initial user interface
   if (!create_gui(ROTATE_0)) return false;

   // Create desktop observer and register for sd insertion/removal events
   if ((desktop_observer = Desktop_CreateSettingObserver()) != NULL)
   {
      Dispatcher_AddListener(GetDispatcherClient()->Get(), desktop_observer);
      GetMessenger()->RegisterListener(SYSCFG_EVENT_SDCARD, this);
      return true;
   }
   return false;
}

// Called when the application stops (redefinition of virtual function)
void EGGxplorer::OnStop()
{
   if (res_factory != NULL) delete res_factory;
   if (string_res != NULL) delete string_res;
   if (image_res != NULL) delete image_res;
   if (layout_studio != NULL) delete layout_studio;
   if (skin_factory != NULL) delete skin_factory;

   // Unregister from sd events and destroy desktop observer
   if (desktop_observer != NULL)
   {
      GetMessenger()->UnRegisterListener(CMessenger::GetEventType(SYSCFG_EVENT_SDCARD), this);
      Dispatcher_RemoveListener(GetDispatcherClient()->Get(), desktop_observer);
      Desktop_DestroySettingObserver(desktop_observer);
   }
}

// Delete window object on shutdown
void EGGxplorer::OnDeleteChildWindow(CSkinWindow *window)
{
   if (window != NULL) window->RequestDestroy();
}

// Handler SD insertion/removal notification
EventReturnType EGGxplorer::OnUserEvent(SharedEventPtr event, EventType event_type,
                                        SharedEventDataPtr event_data)
{
   // Check if this is the event we are looking for
   if (event_type == CMessenger::GetEventType(SYSCFG_EVENT_SDCARD))
   {
      if (main_window) main_window->OnSDNotification((CUserEvent *) event->ToNormalPtr());
      return EVENT_RETURN_CONSUMED;
   }
   return CSkinApp::OnUserEvent(event, event_type, event_data);
}

// Create the GUI based on the rotation of the Zii
bool EGGxplorer::create_gui(RotationType rotate)
{
   // Get the display size and set size for top-level window
   uint32_t width, height;
   GetDisplaySize(DISPLAY_ID, &width, &height);

   // Set position for top-level window
   CRect rect(0, 30, width, height - 30);

   // Destroy window if it already exists
   if (main_window != NULL) main_window->RequestDestroy();

   // Create Main Window
   main_window = new MainWindow(layout_studio, this);
   if (main_window == NULL) return false;
   return main_window->Create(rect, SKIN_DEFAULT, ID_MAINWINDOW, DISPLAY_ID, rotate, NULL);
}
